#include "filter.h"

float BoxFilter::Weight(float x, float y) const
{
	return 1.0;
}
BoxFilter::~BoxFilter()
{
	//if(filterTable) delete [] filterTable;
	SAFE_DELETE_ARRAY(filterTable);
}
void BoxFilter::ComputeFilterTable() const
{
	//precompute filter table
	filterTable = new float [FILTER_TABLE_SIZE * FILTER_TABLE_SIZE];
	float * ftp = filterTable;
	float fy,fx;
	for (int y = 0; y < FILTER_TABLE_SIZE; y++)
	{
		fy = (float(y) + 0.5f) * yWidth / FILTER_TABLE_SIZE;
		for (int x = 0; x < FILTER_TABLE_SIZE; x++)
		{
			fx = (float(x)+0.5f) * xWidth / FILTER_TABLE_SIZE;
			*ftp++ = Weight(fx, fy);
		}
	}
}
float TriangleFilter::Weight(float x, float y) const
{
	return max(0.f, xWidth - fabsf(x)) * max(0.f, yWidth - fabsf(y));
}
TriangleFilter::~TriangleFilter()
{
	//if(filterTable) delete [] filterTable;
	SAFE_DELETE_ARRAY(filterTable);
}
void TriangleFilter::ComputeFilterTable() const
{
	//precompute filter table
	filterTable = new float [FILTER_TABLE_SIZE * FILTER_TABLE_SIZE];
	float * ftp = filterTable;
	float fy,fx;
	for (int y = 0; y < FILTER_TABLE_SIZE; y++)
	{
		fy = (float(y) + 0.5f) * yWidth / FILTER_TABLE_SIZE;
		for (int x = 0; x < FILTER_TABLE_SIZE; x++)
		{
			fx = (float(x)+0.5f) * xWidth / FILTER_TABLE_SIZE;
			*ftp++ = Weight(fx, fy);
		}
	}
}
float GaussianFilter::Weight(float x, float y) const
{
	float gaussian_x = max(0.f, float(expf(-alpha * x * x)- expX));
	float gaussian_y = max(0.f, float(expf(-alpha * y * y)- expY));
	return gaussian_x * gaussian_y;
}
GaussianFilter::~GaussianFilter()
{
	//if(filterTable) delete [] filterTable;
	SAFE_DELETE_ARRAY(filterTable);
}
void GaussianFilter::ComputeFilterTable() const
{
	//precompute filter table
	filterTable = new float [FILTER_TABLE_SIZE * FILTER_TABLE_SIZE];
	float * ftp = filterTable;
	float fy,fx;
	for (int y = 0; y < FILTER_TABLE_SIZE; y++)
	{
		fy = (float(y) + 0.5f) * yWidth / FILTER_TABLE_SIZE;
		for (int x = 0; x < FILTER_TABLE_SIZE; x++)
		{
			fx = (float(x)+0.5f) * xWidth / FILTER_TABLE_SIZE;
			*ftp++ = Weight(fx, fy);
		}
	}
}

float MitchellFilter::Weight(float x, float y) const
{
	return Mitchell1D(x * invXWidth) * Mitchell1D(y * invYWidth);
}
MitchellFilter::~MitchellFilter()
{
	//if(filterTable) delete [] filterTable;
	SAFE_DELETE_ARRAY(filterTable);
}
void MitchellFilter::ComputeFilterTable() const
{
	//precompute filter table
	filterTable = new float [FILTER_TABLE_SIZE * FILTER_TABLE_SIZE];
	float * ftp = filterTable;
	float fy,fx;
	for (int y = 0; y < FILTER_TABLE_SIZE; y++)
	{
		fy = (float(y) + 0.5f) * yWidth / FILTER_TABLE_SIZE;
		for (int x = 0; x < FILTER_TABLE_SIZE; x++)
		{
			fx = (float(x)+0.5f) * xWidth / FILTER_TABLE_SIZE;
			*ftp++ = Weight(fx, fy);
		}
	}
}
float MitchellFilter::Mitchell1D(float x) const
{
	x = fabsf(2.f * x);
	if(x > 1.f)
		return ((-B -6*C) * x*x*x +(6*B + 30*C) * x*x + (-12*B -48*C)* x + (8*B + 24* C)) * (1.f/6.f);
	else
		return ((12 - 9*B - 6*C) * x*x*x + (-18 + 12*B + 6*C)* x*x + (6 - 2*B)) * (1.f/6.f);
}


float LanczosSincFilter::Weight(float x, float y) const
{
	// w(x) = (sinc(PI*x)*sinc(PI*x*tau)
	return Sinc1D(x* invYWidth) * Sinc1D(y * invYWidth);
}
LanczosSincFilter::~LanczosSincFilter()
{
	//if(filterTable) delete [] filterTable;
	SAFE_DELETE_ARRAY(filterTable);
}
void LanczosSincFilter::ComputeFilterTable() const
{
	//precompute filter table
	filterTable = new float [FILTER_TABLE_SIZE * FILTER_TABLE_SIZE];
	float * ftp = filterTable;
	float fy,fx;
	for (int y = 0; y < FILTER_TABLE_SIZE; y++)
	{
		fy = (float(y) + 0.5f) * yWidth / FILTER_TABLE_SIZE;
		for (int x = 0; x < FILTER_TABLE_SIZE; x++)
		{
			fx = (float(x)+0.5f) * xWidth / FILTER_TABLE_SIZE;
			*ftp++ = Weight(fx, fy);
		}
	}
}
float LanczosSincFilter::Sinc1D(float x) const
{
	x = fabsf(x);
	if(x < 1e-5) return 1.f;
	if(x > 1.f)  return 0.f;
	x *= M_PI;
	float sinc = sinf(x * tau) / (x * tau);
	float lanczos = sinf(x) / x;
	return sinc * lanczos;
}